#
# Copyright (c) 2023 supercell
#
# SPDX-License-Identifier: BSD-3-Clause
#

module Luce
  # The spec of GFM about footnotes is
  # [missing](https://github.com/github/cmark-gfm/issues/283#issuecomment-1378868725).
  # For source code of cmark-gfm, See `noMatch` label of
  # `handle_close_bracket` function in [master@c32ef78](https://github.com/github/cmark-gfm/blob/c32ef78/src/inlines.c#L1236).
  # A Rust implementation is also [available](https://github.com/wooorm/markdown-rs/blob/2498e31eecead798efc649502bbf5f86feaa94be/src/construct/gfm_label_start_footnote.rs).
  # Footnote shares the same syntax with `LinkSyntax`,
  # but have a different branch of handling close bracket.
  class FootnoteRefSyntax
    private def self.footnote_label(key : String) : String?
      return nil if key.empty? || key.codepoint_at(0) != Charcode::CARET
      key = key[1..].strip.downcase
      return nil if key.empty?
      key
    end

    def self.try_create_footnote_link(ctx : LinkContext, text : String, secondary : Bool = false) : Array(Node)?
      parser = ctx.parser
      key = footnote_label(text)
      refs = parser.document.footnote_references
      # `label` is what footnote_references stored, it is case-sensitive.
      label = refs.keys.find("") { |k| k.downcase == key }
      # `!count.nil?` means footnote was valid
      count = refs[label]?
      # And then check if footnote was matched
      return nil if key.nil? || count.nil?
      result = [] of Node
      # There are 4 cases here: ![^...], [^...], ![...][^...], [...][^...]
      result << Text.new("!") if ctx.opener.char == Charcode::EXCLAMATION
      refs[label] = (count = count + 1)
      labels = parser.document.footnote_labels
      pos = labels.index(key) || -1
      if pos < 0
        pos = labels.size
        labels << key
      end

      # `children` are text segments after '[^' before ']'.
      children = ctx.get_children.call
      if secondary
        result << Text.new("[")
        result.concat(children)
        result << Text.new("]")
      end
      id = DartURI.encode_component(label)
      suffix = count > 1 ? "-#{count}" : ""
      link = Element.new("a", [Text.new("#{pos + 1}")] of Node)
      link.attributes["href"] = "#fn-#{id}"
      link.attributes["id"] = "fnref-#{id}#{suffix}"
      sup = Element.new("sup", [link] + [] of Node)
      sup.attributes["class"] = "footnote-ref"
      result << sup
      result
    end
  end
end
